<template>
    <el-form
      ref="smsLoginForm"
      :model="smsFormData"
      status-icon
      :rules="smsRules"
      label-width="120px"
      class="demo-smsFormData"
    >
    <!-- 输入手机号 -->
    <el-form-item label="手机号" prop="phone" class="captcha-form-item">
        <el-input v-model="smsFormData.phone" maxlength="11" />
        <span class="yzm" @click="sendSms">{{desc}}</span>
      </el-form-item>
      <!-- 输入验证码 -->
      <el-form-item label="验证码" prop="code" class="password-form-item">
        <el-input v-model="smsFormData.code" type="text" autocomplete="off" maxlength="5"/>
      </el-form-item>
      
      <el-form-item>
        <el-button type="primary" @click="submitForm(smsLoginForm)">提交</el-button>
      </el-form-item>
    </el-form>
</template>
<script setup>

//业务：

// 1.修改表单注入的数据以及prop

// 2.给smsLogin这个组件添加自己的表单Form校验规则

  import { reactive, ref,onUnmounted } from 'vue'
  //引入校验函数
  import {smsRules,useSubmitForm} from "../../composition/login/validate"

  // 引入发送请求的方法

  import * as api from "@/api/users"

  // 引入element中的消息提示组件

  import { ElMessage } from 'element-plus'

  // 引入store

  import {useUser} from "@/store/users"

  // 引入loading加载动画框
  import { ElLoading } from 'element-plus'

  // 引入路由对象
  import {useRouter} from "vue-router"

  let router = useRouter()

  // 使用store

  let userStore = useUser()



  //表单校验成功之后，回调的方法
  let validateSuccess = async () => {
    // console.log("校验成功")
    // 发起登入请求的时候就要加载loading加载动画框
    let loadingInstance = ElLoading.service({
      // lock:true,
      text:'正在登入...',
      background:'rgba(0,0,0,.3)'
    })
    // 发送短信登入的请求
    try{
      let res = await api.smsApi(smsFormData.code)
      // 关闭loading加载动画框
      loadingInstance.close()
      // 存储token，存到sessionStorage中
      sessionStorage.setItem("sx-token",res.data.token)
      // 存储用户信息
      userStore.$patch({
        userInfo:res.data.userInfo
      })
      // console.log(res)
      // 页面要跳转
      router.push("/")
    }catch(e){
      console.log(e)
      // 登入失败也要关闭loading动画
      loadingInstance.close()
    }
  }

  //表单校验成功之后，回调的方法
  let validateFailed =  () => {
    console.log("校验失败")

    
  }

  //使用submitForm

  let submitForm = useSubmitForm(validateSuccess,validateFailed)

  const smsLoginForm = ref()

  //注入到表单的数据

  const smsFormData = reactive({
    phone: '',
    code: '',
  })
  
  //短信登入流程

  //1.输入手机号，点击发送短信，获取短信验证码

  // 短信验证码需要进行倒计时

  // 手机验证码同一个手机，一分钟只能发送一次，一天一个手机号只能发6条
  
  // 2.输入短信验证码,进入请求

  // 声明一个响应式变量，来改变按钮中间的文字

  let desc = ref("点击发送")
  // 引用定时器，便于组件卸载的时候，清除定时器
  let timeDownInterval=null;
  // 处理用户频繁点击的问题
  // 应用开关的思路
  // 初始值用户未点击
  let isClick = false;

  let sendSms = async () => {
    
    
      // 发起获取短信验证码请求
      try{
        let res = await api.getSmsCode(smsFormData.phone)
        // 给消息提示
        ElMessage({
          message: '短信验证码发送成功',
          type: 'success',
        })
        // console.log(res)
        // 调用倒计时函数
        timeDownInterval = timeDown(10,desc,'秒后重发',desc.value,
        ()=>{
          // 让点击状态isClick回到未点击状态
          isClick=false
        })
      
      }catch(e){
        // console.log(e)
        // 将按钮的开关重置
        isClick = false
        ElMessage({
          message: e,
          type: 'error',
        })
        return
      }
    
    
    // 标记isClick已经被点击了
    isClick = true;
  }

  // 短信倒计时方法
  /**
   * 
   * @param {Number} timer 倒计时的时间
   * @param {Object} param 需要变更的响应式变量
   * @param {String} msg 倒计时秒数的文字
   * @param {String} endMsg 倒计时结束，回显的文字
   * @param {Function} cb 倒计时结束之后回调的函数
   */

  //  封装的思路，目的就是为了让使用能够变简单，复杂的逻辑放在函数内部

    // 字符串.padStart('希望几位数','用什么字符去补')

  let timeDown = (timer=5,param,msg,endMsg,cb) => {
    //实现思路，核心就是间隔定时器
    let count = timer;
    // 一点用倒计时函数，就要显示倒计时秒数
    param.value = (count+"").padStart(2,0)+msg
    let interval = setInterval(()=>{
      count--
      
      if(count<=0){
      // 清除定时器
      clearInterval(interval)
      // 倒计时结束
      param.value=endMsg
      // 回调传入的函数
      cb && cb ()
      return
    }
    param.value = (count+"").padStart(2,0)+msg
    },1000)
    // 返回定时器的引用
    return interval
  }

  // 组件卸载的钩子
  onUnmounted(()=>{
    // 卸载定时器
    // 如果定时器存在，组件卸载的时候定时器也要清除
    if(timeDownInterval) clearInterval(timeDownInterval)
  })
  
  </script>